//
//  MDHWKWebViewController.m
//  JSTech
//
//  Created by 高得华 on 2019/5/28.
//  Copyright © 2020 华&梅. All rights reserved.
//

#import "MDHWKWebViewController.h"
#import "WKWebViewJavascriptBridge.h"
#if __has_include("MDHPT/MDHPT-Swift.h")
#import "MDHPT/MDHPT-Swift.h"
#else
#import "JSTech-Swift.h"
#endif



// WKWebView 内存不释放的问题解决
@interface WeakWebViewScriptMessageDelegate : NSObject<WKScriptMessageHandler>

//WKScriptMessageHandler 这个协议类专门用来处理JavaScript调用原生OC的方法
@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;

@end

@implementation WeakWebViewScriptMessageDelegate

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate {
    self = [super init];
    if (self) {
        _scriptDelegate = scriptDelegate;
    }
    return self;
}

//MARK: - WKScriptMessageHandler
//遵循WKScriptMessageHandler协议，必须实现如下方法，然后把方法向外传递
//通过接收JS传出消息的name进行捕捉的回调方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([self.scriptDelegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
        [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
    }
    /*
    WKWebView * webView = message.webView;
    MDHViewModelServicesImpl * services = [MDHRouter sharedInstance].services;
    if (kMDHWebVCM().blockPushScriptNextVc) {
        kMDHWebVCM().blockPushScriptNextVc(userContentController, message, webView);
    }else{
        if ([message.name isEqualToString:@"getUserAccount"]) {
            NSString *userId =[NSString stringWithFormat:@"sendUserAccount('%@')",services.client.currentUser.perfect_number];
            [webView evaluateJavaScript:userId completionHandler:^(id _Nullable result, NSError * _Nullable error) {
                DTLog(@"error:%@",error);
            }];
        }
        else if ([message.name isEqualToString:@"pageJumpRecharge"]) {
            MMWalletRechargeViewModel * vm = [[MMWalletRechargeViewModel alloc] initWithServices:services params:@{}];
            [services pushViewModel:vm animated:true];
        }
        else if ([message.name isEqualToString:@"getAppKey"]) {
            NSString * tok1 = services.client.currentUser.app_key;
            NSString *token = [NSString stringWithFormat:@"sendAppKey('%@')",tok1];
            [webView evaluateJavaScript:token completionHandler:^(id _Nullable result, NSError * _Nullable error) {
                DTLog(@"error:%@",error);
            }];//
        }
        else if ([message.name isEqualToString:@"getRoomId"]) {
            NSString * room_id = kMDHCMMQ().room_id;
            if (room_id.length > 0) {
                NSString *token = [NSString stringWithFormat:@"sendRoomId('%@')",room_id];
                [webView evaluateJavaScript:token completionHandler:^(id _Nullable result, NSError * _Nullable error) {
                    DTLog(@"error:%@",error);
                }];//
            }
        }
    }*/
}

@end


@interface MDHWKWebViewController ()
<
WKScriptMessageHandler
> {
    NSArray * _scriptMessages;
}

///返回按钮
@property (nonatomic, strong, readwrite) UIBarButtonItem * customBackBarItem;
///关闭按钮
@property (nonatomic, strong, readwrite) UIBarButtonItem * closeButtonItem;
///刷新控件按钮
@property (nonatomic, strong, readwrite) UIBarButtonItem * barBtnItemRefresh;
///ViewModel
@property (nonatomic, strong, readwrite) MDHWebViewModel * viewModel;

///显示文字
@property (nonatomic, strong) UILabel *originLabel;
/// WKWebViewJavascriptBridge 桥接
@property (nonatomic, strong) WKWebViewJavascriptBridge* bridge;

@end

@implementation MDHWKWebViewController

@synthesize viewModel = _viewModel;

- (instancetype)initWithViewModel:(MDHViewModel *)viewModel {
    self = [super initWithViewModel:viewModel];
    if (self) {
        //self.viewModel.url = @"https://www.baidu.com";
        switch (self.viewModel.loadType) {
            case MDHWebViewLoadTypeLoadWebURL:
                self = [self initWithURLString:self.viewModel.url];
                break;
            case MDHWebViewLoadTypeLoadWebHTML:
                break;
            case MDHWebViewLoadTypePOSTWebURL:
                break;
            default:
                break;
        }
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    ///设置标题 [GEdwardInfoController sharedInstance].CFBundleDisplayName
    self.viewModel.title = @"加载中...";
    
    ///js注册方法
    _scriptMessages = @[];//@[@"getUserAccount", @"getAppKey", @"pageJumpRecharge", @"goShare", @"goCheckout", @"getRoomId", @"val"];
    
    //拦截每次请求的url
    //self.needInterceptRequest = true;
    self.progressTintColor = [UIColor greenColor];
    self.backItem = nil;
    self.closeItem = nil;
    self.backItem = self.customBackBarItem;
    self.closeItem = self.closeButtonItem;
    self.navigationItem.rightBarButtonItem = self.barBtnItemRefresh;
    
    ///设置页面
    [self setup_webview];
    
    ///重新注入数据
    [self reinjectData];
}

///重新加载时
- (void)setup_webview {
    self.webView.opaque = false;
    ///注册
    [self.webView addObserver:self forKeyPath:@"URL" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionOld context:NULL];
    ///监听 UIScrollView的滑动
    [self.webView.scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:@"JBContext"];
    /*[self.webView.scrollView mh_addHeaderRefresh:^(MJRefreshStateHeader * _Nullable header) {
        @strongify(self);
        //header.alpha = 1.f;
        [self roadLoadClicked];
    }];*/
    [self removeJS];
    [self addJS];
    ///重新注入数据
    [self reinjectData];
}

#pragma mark- KVO
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context{
    id value = change[NSKeyValueChangeNewKey];
    id oldValue = change[NSKeyValueChangeOldKey];
    if ([value isKindOfClass:[NSNull class]]) {
        value = nil;
    }
    if ([oldValue isKindOfClass:[NSNull class]]) {
        oldValue = nil;
    }
    
    if ([object isKindOfClass:[UIScrollView class]]) {
        if ([keyPath isEqualToString:@"contentOffset"]) {
            CGPoint offset = [value CGPointValue];
            float currentPostion = offset.y;
            CGFloat alpha = 0;
            if (currentPostion < -40) {
                alpha = fabsf(currentPostion + 40) / 40;
            }
            self.originLabel.alpha = currentPostion == 0 ? 0:alpha;
            /*BOOL canGoBool = self.config.canGoForward || self.config.canGoBack;
            if (currentPostion - lastPostion > scrollJudgeDistance)  {
                lastPostion = currentPostion;
                [self bottomBarHidden:YES];
            } else if ((lastPostion - currentPostion > scrollJudgeDistance) && canGoBool) {
                lastPostion = currentPostion;
                [self bottomBarHidden:NO];
            }*/
        }
    }else if ([object isKindOfClass:[WKWebView class]]) {
        if ([keyPath isEqualToString:@"URL"]) {
            if (value) {
                NSString * text1 = [NSString stringWithFormat:@"%@%@%@", @"此网页由 ",((NSURL *)value).host, @" 提供"];
                self.originLabel.text = text1;
                //self.previousURL = value;
            } else {
                //self.previousURL = oldValue;
            }
            if (!value && !oldValue) {
                [(WKWebView *)object reload];
            }
        }else{
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }
    }else{
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)addJS {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
        WeakWebViewScriptMessageDelegate * weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
        //这个类主要用来做native与JavaScript的交互管理
        WKUserContentController * wkUController = self.webView.configuration.userContentController;//[[WKUserContentController alloc] init];
        for (NSString *methodName in self->_scriptMessages) {
            [wkUController addScriptMessageHandler:weakScriptMessageDelegate name:methodName];
        }
    });
}

- (void)removeJS {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //这个类主要用来做native与JavaScript的交互管理
        WKUserContentController * wkUController = self.webView.configuration.userContentController;//[[WKUserContentController alloc] init];
        for (NSString *name in self->_scriptMessages) {
            [wkUController removeScriptMessageHandlerForName:name];
        }
    });
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self removeJS];
}

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self removeJS];
    [self addJS];
}

/*
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [(MDHNavigationController *)AppDelegate.navigationController navigation_top_vc];
}*/

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    //设置布局
    self.webView.mh_y = kMMWPTFC().kNavSafeArea;
    self.webView.mh_height = self.view.mh_height-kMMWPTFC().kNavSafeArea-kMMWPTFC().kSafeAreaBottom;
    if (self.blockViewDidLayoutSubviews) {
        self.blockViewDidLayoutSubviews();
    }
}

//- (void)willMoveToParentViewController:(UIViewController *)parent {
//    [super willMoveToParentViewController:parent];
//
//}
- (void)didMoveToParentViewController:(UIViewController *)parent {
    [super didMoveToParentViewController:parent];
    if (!parent) {
        [self dealloc_view:true];
    }
}

- (UIEdgeInsets)contentInset {
    if (self.viewModel.prefersNavigationBarHidden) {
        return UIEdgeInsetsMake(-kMMWPTFC().kNavSafeArea, 0, kMMWPTFC().kSafeAreaBottom, 0);
    }
    return UIEdgeInsetsMake(kMMWPTFC().kNavSafeArea, 0, kMMWPTFC().kSafeAreaBottom, 0);
}

- (void)dealloc_view:(BOOL)isAll {
    if (self.webView) {
        //移除注册的js方法
        //移除观察者
        //[self.webView removeObserver:self forKeyPath:@"estimatedProgress"];
        //[self.webView removeObserver:self forKeyPath:@"title"];
        /// @"URL"
        @try {
            [self.webView removeObserver:self forKeyPath:@"URL"];
        }@catch (NSException *exception) {
            DTLog(@"URL多次删除kvo 报错了");
        }
        /// @"contentOffset"
        @try {
            [self.webView.scrollView removeObserver:self forKeyPath:@"contentOffset" context:@"JBContext"];
        }@catch (NSException *exception) {
            DTLog(@"contentOffset 多次删除kvo 报错了");
        }
        if (isAll) {
            for (NSString *name in _scriptMessages) {
                [self.webView.configuration.userContentController removeScriptMessageHandlerForName:name];
            }
            _scriptMessages = nil;
        }
        [self.webView stopLoading];
        [self.webView setNavigationDelegate:nil];
        [self.webView setUIDelegate:nil];
        /*//self.webView.scrollView.mj_header = nil;
        [self.webView removeFromSuperview];
        self.webView = nil;
        [[JXBWKWebViewPool sharedInstance] cleanReusableViews];*/
    }
    _bridge = nil;
    self.originLabel = nil;
}

- (void)dealloc{
    //移除注册的js方法
    //[self dealloc_view:true];
    self.closeButtonItem = nil;
    self.barBtnItemRefresh = nil;
    self.customBackBarItem = nil;
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

//MARK: - WKScriptMessageHandler
//遵循WKScriptMessageHandler协议，必须实现如下方法，然后把方法向外传递
//通过接收JS传出消息的name进行捕捉的回调方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    WKWebView * webView = message.webView;
    if (kMDHWebVCM().blockPushScriptNextVc) {
        kMDHWebVCM().blockPushScriptNextVc(userContentController, message, webView);
    }
}

//MARK: - ================ 加载方式
- (void)didFinishLoad {
    [super didFinishLoad];
    //[self.webView.scrollView.mj_header endRefreshing];
    //self.webView.scrollView.mj_header.alpha = 0.001f;
}
- (void)didFailLoadWithError:(NSError *)error {
    [super didFailLoadWithError:error];
    //[self.webView.scrollView.mj_header endRefreshing];
    //self.webView.scrollView.mj_header.alpha = 0.001f;
}

/// 重新注入 服务需要的数据
- (void)reinjectData {
    /// jsBridge
#if DEBUG
    [WKWebViewJavascriptBridge enableLogging];
#endif
    _bridge = [WKWebViewJavascriptBridge bridgeForWebView:self.webView];
    [_bridge setWebViewDelegate:self];
    
    //JS第一个按钮点击事件
    [self.bridge registerHandler:@"callNativeApp" handler:^(id data, WVJBResponseCallback responseCallback) {
        //handler在主线程
        DTLog(@"thread = %@", [NSThread currentThread]);
        //responseCallback([NSString stringWithFormat:@"成功调用OC的%@方法", [data valueForKey:@"action"]]);
        if (![kMDHWebVCM() pushWithUrl:data]) {
            responseCallback(@"");
        }
    }];
    
    ///给服务器一些数据
    MDHHTTPService * client = self.viewModel.services.client;
    NSMutableDictionary * dict = [[[MDHURLExtendsParameters extendsParameters] mj_JSONObject] mutableCopy];
    [dict removeObjectForKey:@"authorization"];
    [dict removeObjectForKey:@"time_stamp"];
    dict[@"token"] = client.token;
    NSString * roomid = @"";
    if (roomid.length > 0) {
        dict[@"room_id"] = roomid;
    }
    NSString * data = [dict mj_JSONString];
    [_bridge callHandler:@"functionInJs" data:data responseCallback:^(id responseData) {
        DTLog(@"functionInJs -> responseData = %@", responseData);
    }];
}

///重新加载
- (void)roadLoadClicked {
    //[self dealloc_view:false];
    //[self setup_viewUi];
    //[self setup_webview];
    ///重新注入数据
    [self reinjectData];
    [self reload];
}
- (void)customBackItemClicked {
    if (self.canGoBack) {
        [self goBack];
    }else{
        [self closeItemClicked];
    }
}

///关闭按钮的点击响应事件
- (void)closeItemClicked {
    //移除注册的js方法
    //[self dealloc_view:true];
    [self.navigationController popViewControllerAnimated: true];
}

//MARK: - ===== 懒加载 ===== -
// 关闭按钮
- (UIBarButtonItem*)closeButtonItem {
    if (!_closeButtonItem) {
        UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.mh_size = CGSizeMake(36, kMMWPTFC().kNavBarHeight);
        [btn setTitle:@"关闭" forState:UIControlStateNormal];
        [btn setTitleColor:kColor_MDHTheme() forState:UIControlStateNormal];
        [btn setTitleColor:kColor_MDHTheme() forState:UIControlStateHighlighted];
        [btn.titleLabel setFont:[UIFont systemFontOfSize:16]];
        //设置内容偏移量
        //btn.contentEdgeInsets = UIEdgeInsetsMake(0, -22, 0, 0);
        [btn addTarget:self action:@selector(closeItemClicked) forControlEvents:UIControlEventTouchUpInside];
        _closeButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btn];
    }
    return _closeButtonItem;
}

// 返回按钮
- (UIBarButtonItem*)customBackBarItem {
    if (!_customBackBarItem) {
        UIImage* backItemImage = [UIImage imageNamed:kCommonNavButtonBack];
        UIImage* backItemHlImage = backItemImage;
        UIButton * backButton = [UIButton buttonWithType:UIButtonTypeCustom];
        backButton.mh_size = CGSizeMake(36, kMMWPTFC().kNavBarHeight);
        [backButton setImage:backItemImage forState:UIControlStateNormal];
        [backButton setImage:backItemHlImage forState:UIControlStateHighlighted];
        backButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
        //设置内容偏移量
        //backButton.contentEdgeInsets = UIEdgeInsetsMake(0, -22, 0, 0);
        [backButton addTarget:self action:@selector(customBackItemClicked) forControlEvents:UIControlEventTouchUpInside];
        _customBackBarItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    }
    return _customBackBarItem;
}

// 刷新控件
- (UIBarButtonItem *)barBtnItemRefresh {
    if (!_barBtnItemRefresh) {
        UIImage* backItemImage = [[UIImage imageNamed:@"common_nav_btn_refresh"] imageByTintColor:kColor_MDHTheme()];
        UIImage* backItemHlImage = backItemImage;
        UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.mh_size = CGSizeMake(36, kMMWPTFC().kNavBarHeight);
        [btn setImage:backItemImage forState:UIControlStateNormal];
        [btn setImage:backItemHlImage forState:UIControlStateHighlighted];
        //设置内容偏移量
        //btn.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -22);
        [btn addTarget:self action:@selector(roadLoadClicked) forControlEvents:UIControlEventTouchUpInside];
        _barBtnItemRefresh = [[UIBarButtonItem alloc] initWithCustomView:btn];
    }
    return _barBtnItemRefresh;
}

- (UILabel *)originLabel {
    if (!_originLabel) {
        UILabel *label = [[UILabel alloc] init];
        label.font = [UIFont systemFontOfSize:12];
        label.textColor = [UIColor lightGrayColor];
        label.textAlignment = NSTextAlignmentCenter;
        _originLabel = label;
        [label setFrame:CGRectMake(10, 30, self.view.mh_width - 20, 35)];
        [self.webView insertSubview:label belowSubview:self.webView.scrollView];
    }
    return _originLabel;
}

@end
